<template>
  <div>
    <div ref='display'></div>
  </div>
</template>
<script>
import Vue from 'vue'
import randomStr from '../../utils/random_str'
export default {
  name: 'i-display',
  props: {
    code: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      html: '',
      js: '',
      css: '',
      id: randomStr()
    }
  },
  watch: {
    code () {
      this.destoryCode()
      this.renderCode()
    }
  },
  methods: {
    getSource (source, type) {
      const regexp = new RegExp(`<${type}[^>]*>`)
      let openingTag = source.match(regexp)
      if (!openingTag) return ''
      else openingTag = openingTag[0]
      let start = source.indexOf(openingTag) + openingTag.length
      let end = source.lastIndexOf(`</${type}>`)
      return source.slice(start, end)
    },
    spiltCode () {
      const script = this.getSource(this.code, 'script').replace(/export default/, 'return')
      const style = this.getSource(this.code, 'style')
      const template = '<div id="app">' + this.getSource(this.code, 'template') + '</div>'
      this.js = script
      this.css = style
      this.html = template
    },
    renderCode () {
      this.spiltCode()
      if (this.html !== '' && this.js !== '') {
        const parseStrToFunc = new Function(this.js)()
        parseStrToFunc.template = this.html
        const Component = Vue.extend(parseStrToFunc)
        this.component = new Component().$mount()
        this.$refs.display.appendChild(this.component.$el)
        if (this.css !== '') {
          const style = document.createElement('style')
          style.type = 'text/css'
          style.id = this.id
          style.innerHTML = this.css
          document.getElementsByTagName('head')[0].appendChild(style)
        }
      }
    },
    destoryCode () {
      const $target = document.getElementById(this.id)
      if ($target) $target.parentNode.removeChild($target)
      if (this.component) {
        this.$refs.display.removeChild(this.component.$el)
        this.component.$destory()
        this.component = null
      }
    }
  },
  mounted () {
    this.renderCode()
  },
  beforeDestroy () {
    this.destoryCode()
  }
}
</script>